#include "led.h"
#include <esp_log.h>

#define TAG "Led"

Led::Led(gpio_num_t gpio, bool common_anode)
    : m_led(gpio), m_common_anode(common_anode)
{
    ESP_LOGI(TAG, "gpio:%d, common_anode:%s", gpio, common_anode ? "true" : "false");

    // 配置引脚、关闭输出
    gpio_config_t led_config = {
        .pin_bit_mask = 1ULL << m_led,
        .mode = GPIO_MODE_OUTPUT,
        .pull_up_en = GPIO_PULLUP_ENABLE,
        .pull_down_en = GPIO_PULLDOWN_DISABLE,
        .intr_type = GPIO_INTR_DISABLE
    };
    ESP_ERROR_CHECK(gpio_config(&led_config));
    gpio_set_level(m_led, m_common_anode ? 1 : 0);

    // 配置定时器
    esp_timer_create_args_t timer_args = {
        .callback = [](void *arg) {
            auto led = static_cast<Led *>(arg);
            led->LedTimerCallback();
        },
        .arg = this,
        .dispatch_method = ESP_TIMER_TASK,
        .name = "led_timer",
        .skip_unhandled_events = true   
    };
    ESP_ERROR_CHECK(esp_timer_create(&timer_args, &m_timer_handle));
}

Led::~Led()
{
    esp_timer_stop(m_timer_handle);
    esp_timer_delete(m_timer_handle);
}

void Led::TurnOn()
{
    std::lock_guard<std::mutex> lock(m_mutex);
    gpio_set_level(m_led, m_common_anode ? 1 : 0);
}

void Led::TurnOff()
{
    std::lock_guard<std::mutex> lock(m_mutex);
    gpio_set_level(m_led, m_common_anode ? 0 : 1);
}

void Led::BlinkOnce()
{
    m_blink_times = 2;
    m_continuous_blink = false;
    esp_timer_stop(m_timer_handle);
    esp_timer_start_periodic(m_timer_handle, 1000);
    std::lock_guard<std::mutex> lock(m_mutex);
    gpio_set_level(m_led, m_common_anode ? 0 : 1);
}

void Led::Blink(int times, int interval_ms)
{
    m_blink_times = times << 1;
    m_interval_ms = interval_ms;
    m_continuous_blink = false;
    esp_timer_stop(m_timer_handle);
    esp_timer_start_periodic(m_timer_handle, m_interval_ms * 1000);
    std::lock_guard<std::mutex> lock(m_mutex);
    gpio_set_level(m_led, m_common_anode ? 0 : 1);
}

void Led::StartContinuousBlink(int interval_ms)
{
    m_continuous_blink = true;
    m_interval_ms = interval_ms;
    esp_timer_stop(m_timer_handle);
    esp_timer_start_periodic(m_timer_handle, m_interval_ms * 1000);
    std::lock_guard<std::mutex> lock(m_mutex);
    gpio_set_level(m_led, m_common_anode ? 0 : 1);
}


// 定时器回调函数
void Led::LedTimerCallback()
{
    this->m_blink_times--;
    std::lock_guard<std::mutex> lock(this->m_mutex);
    if(this->m_blink_times & 1) {
        gpio_set_level(this->m_led, this->m_common_anode ? 1 : 0);
    } else {
        gpio_set_level(this->m_led, this->m_common_anode ? 0 : 1);
        if(this->m_blink_times == 0 && !this->m_continuous_blink) {
            esp_timer_stop(this->m_timer_handle);
        }
    }
}
